<!--
 * @Description: 虚拟下拉选择框
 * @Author: James324
 * @Date: 2023-10-27 15:42:34
 * @LastEditors: James324
 * @LastEditTime: 2024-03-12 15:29:06
-->
<script setup lang="ts">
import { cloneDeep } from 'lodash-es';
import { CircleClose } from '@element-plus/icons-vue';
import { TagProps } from 'element-plus';

interface Props {
    modelValue: any;
    placeholder?: string;
    disabled?: boolean;
    closable?: boolean;
    clear?: boolean;
    maxCollapseTags?: number;
    type?: 'success' | 'info' | 'warning' | 'danger';
    popoverWidth?: number | string;
    tagAttrs?: PickComponentsProps<TagProps>;
}
const props = withDefaults(defineProps<Props>(), {
    value: '',
    placeholder: '请选择',
    disabled: false,
    clear: true,
    maxCollapseTags: 1,
    type: 'info',
    popoverWidth: 'auto'
});

const emit = defineEmits(['update:modelValue', 'click', 'close', 'clear']);

const clearIcon = ref(false);
const valueIsArray = computed(() => Array.isArray(props.modelValue)); // 传入值是否为数组
const tagList = computed(() => props.modelValue.slice(0, props.maxCollapseTags)); // 直接展示的 tag 标签列表
const collaspeTags = computed(() => props.modelValue.slice(props.maxCollapseTags)); // 折叠的 tag 标签列表集合
const collapseTagsNum = computed(() => collaspeTags.value.length); // 显示折叠的标签数量

// 选择框移入
const handleOver = () => {
    if (props.disabled) return;
    clearIcon.value = !!props.modelValue;
};

const handleClick = () => {
    if (props.disabled) return;
    emit('click');
};

/**
 * 关闭 tag 标签
 */
const handleCloseTag = (currentData: string) => {
    const index = props.modelValue.findIndex((item: string) => item === currentData);
    const data = cloneDeep(props.modelValue);
    data.splice(index, 1); // 删除对应 tag 标签
    emit('update:modelValue', data);
    emit('close', index);
};
</script>

<template>
    <div
        :class="[
            'm-virtual-input',
            'el-input__wrapper',
            { 'is-disabled': disabled, 'is-tag': valueIsArray && modelValue.length }
        ]"
        @mouseover="handleOver"
        @mouseout="clearIcon = false"
        @click="handleClick"
    >
        <div v-if="!modelValue || !tagList.length">{{ props.placeholder }}</div>
        <div v-else class="is-padding virtual-content">
            <template v-if="!valueIsArray">
                {{ modelValue }}
            </template>
            <div v-else class="m-virtual__tag">
                <el-tag
                    v-for="(item, index) in tagList"
                    :key="item"
                    :class="{ 'm-l-4': index }"
                    :closable="closable"
                    :type="type"
                    v-bind="tagAttrs"
                    @close="handleCloseTag(item)"
                    ><q-tooltip :content="item"
                /></el-tag>
                <!-- 折叠标签 -->
                <el-popover
                    v-if="collapseTagsNum"
                    placement="bottom"
                    :width="popoverWidth"
                    trigger="hover"
                >
                    <template #reference>
                        <el-tag class="m-l-4" :type="type" v-bind="tagAttrs">
                            +{{ collapseTagsNum }}
                        </el-tag>
                    </template>
                    <div>
                        <el-tag
                            v-for="(item, index) in collaspeTags"
                            :key="item"
                            :class="[{ 'm-r-4': index !== collaspeTags.length - 1 }]"
                            :closable="closable"
                            :type="type"
                            v-bind="tagAttrs"
                            @close="handleCloseTag(item)"
                        >
                            {{ item }}
                        </el-tag>
                    </div>
                </el-popover>
            </div>
        </div>
        <div v-if="!valueIsArray && clear" class="m-virtual-input__icon">
            <q-icon v-if="!clearIcon" size="16px" icon-class="" v-bind="$attrs" />
            <template v-else>
                <el-icon
                    size="16px"
                    @click.stop="
                        () => {
                            emit('update:modelValue', '');
                            emit('clear');
                        }
                    "
                    ><CircleClose
                /></el-icon>
            </template>
        </div>
    </div>
</template>

<style lang="scss" scoped>
$disabledColor: #bfbfbf;

.dark {
    .m-virtual-input {
        --m-virtual-input-bg-color: var(--el-disabled-bg-color);
    }
}

/* 虚拟输入框类名 */
.m-virtual-input {
    --el-input-hover-border-color: #c0c4cc;
    --m-virtual-input-bg-color: var(--el-disabled-bg-color);

    @include flex(space-between, center);

    box-sizing: border-box;
    flex: 100%;
    min-height: 26px;
    padding: 0 11px 2px;
    font-size: 14px;
    line-height: 30px;
    color: var(--q-color-info-light-5);
    cursor: pointer;
    border-radius: var(--q-popper-border-radius);
    box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color)) inset;

    &__icon {
        @include flex;

        position: relative;
        top: 1px;
    }

    @include when(disabled) {
        color: $disabledColor;
        cursor: not-allowed;
        -webkit-text-fill-color: $disabledColor;
        background-color: var(--el-disabled-bg-color);
    }

    @include when(tag) {
        padding-right: 4px;
        padding-left: 4px;
    }

    @include pseudo(active) {
        background: var(--m-virtual-input-bg-color);
        box-shadow: 0 0 0 1px #409eff inset;
    }

    :deep() {
        .el-tag__content {
            max-width: 60px;
        }
    }
}

.m-virtual__tag {
    width: 100%;
}

.virtual-content {
    width: 100%;
    @include utils-ellipsis();
}
</style>
